package com.ego.product.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.ego.common.constant.SystemConstant;
import com.ego.product.service.CategoryBrandRelationService;
import com.ego.product.vo.SecondLevelCategoryVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import com.ego.product.dao.CategoryDao;
import com.ego.product.po.Category;
import com.ego.product.service.CategoryService;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author KamTang
 * @program: ego
 * @description 商品三级分类对应实现类
 * @date 2022-11-13 12:56:14
 */
@Service("categoryService")
public class CategoryServiceImpl extends ServiceImpl<CategoryDao, Category> implements CategoryService {

    @Autowired
    private CategoryBrandRelationService categoryBrandRelationService;

    @Override
    @Cacheable(value = {"category"}, key = "#root.methodName", sync = true)
    public List<Category> cascade() {
        // 1、查出所有分类
        List<Category> entities = baseMapper.selectList(null);
        // 2、组装成父子的树形结构
        // 2.1、找到所有的一级分类
        // 使用filter进行过滤，将ParentCid为0的分类收集起来
        return entities.stream().filter(categoryEntity ->
                        categoryEntity.getParentCid() == SystemConstant.CategoryType.TOP.getCode())
                .peek((menu) -> menu.setChildren(getChildren(menu, entities)))
                .sorted(Comparator.comparingInt(menu -> (menu.getSort() == null ? 0 : menu.getSort())))
                .collect(Collectors.toList());
    }

    @Override
    public Long[] getCategoryPath(Long categoryId) {
        List<Long> paths = new ArrayList<>();
        List<Long> parentPath = getParentPath(categoryId, paths);
        Collections.reverse(parentPath);
        return parentPath.toArray(new Long[0]);
    }

    @Override
    @CacheEvict(value = "category", allEntries = true)
    @Transactional(rollbackFor = {Exception.class})
    public void updateCascade(Category category) {
        this.updateById(category);
        categoryBrandRelationService.updateCategory(category.getCatId(), category.getName());
    }

    @Override
    public List<Category> getTopCategory() {
        return this.baseMapper.selectList(new QueryWrapper<Category>().eq("parent_cid", SystemConstant.CategoryType.TOP.getCode()));
    }

    @Override
    public Map<String, List<SecondLevelCategoryVo>> getCategoryJson() {
        // 全部分类
        List<Category> categories = this.baseMapper.selectList(null);
        // 获取顶级分类
        List<Category> topCategories = getParent(categories, SystemConstant.CategoryType.TOP.getCode());
        // 封装为Map结构
        return topCategories.stream().collect(Collectors.toMap(k -> k.getCatId().toString(), v -> {
            // 每一个一级分类，查到这个一级分类的二级分类
            List<Category> secondLevelCategories = getParent(categories, v.getParentCid());
            // 封装上面的结果
            List<SecondLevelCategoryVo> secondLevelCategoryVos = new ArrayList<>();
            if (!CollectionUtils.isEmpty(secondLevelCategories)) {
                secondLevelCategoryVos = secondLevelCategories.stream().map(secondLevelCategory -> {
                    SecondLevelCategoryVo secondLevelCategoryVo = new SecondLevelCategoryVo()
                            .init(v, secondLevelCategory, null);
                    // 找当前二级分类的三级分类封装成vo
                    List<Category> thirdLevelCategories = getParent(categories, secondLevelCategory.getCatId());
                    if (!CollectionUtils.isEmpty(thirdLevelCategories)) {
                        // 封装成指定格式
                        List<SecondLevelCategoryVo.ThirdLevelCategoryVo> thirdLevelCategoryVos = thirdLevelCategories
                                .stream().map(thirdLevelCategory -> new SecondLevelCategoryVo.ThirdLevelCategoryVo()
                                        .init(secondLevelCategory, thirdLevelCategory)).collect(Collectors.toList());
                        secondLevelCategoryVo.setThirdLevelCategoryVo(thirdLevelCategoryVos);
                    }
                    return secondLevelCategoryVo;
                }).collect(Collectors.toList());
            }
            return secondLevelCategoryVos;
        }));
    }

    private List<Category> getParent(List<Category> sources, Long parentId) {
        return sources.stream().filter(source -> source.getParentCid().equals(parentId))
                .collect(Collectors.toList());
    }

    /**
     * [225,25,2]
     *
     * @param categoryId 分类ID
     * @param paths     分类ID数组
     * @return [225, 25, 2]
     */
    private List<Long> getParentPath(Long categoryId, List<Long> paths) {
        // 收集当前节点ID
        paths.add(categoryId);
        Category category = this.getById(categoryId);
        if (category.getParentCid() != 0) {
            getParentPath(category.getParentCid(), paths);
        }
        return paths;
    }

    /**
     * 递归找到每一个菜单的子分类
     *
     * @param root 当前分类
     * @param all  所有分类
     * @return
     */
    private List<Category> getChildren(Category root, List<Category> all) {
        // 如果分类的父id和一级分类的id一样，说明此分类categoryEntity为root的子分类
        return all.stream().filter(categoryEntity -> {
                    return categoryEntity.getParentCid().equals(root.getCatId());
                    // 将这样的分类收集起来
                }).peek(categoryEntity -> {
                    // 通过递归再将上面的分类categoryEntity进行同样的操作，找出是否还有子分类
                    categoryEntity.setChildren(getChildren(categoryEntity, all));
                    // 把当前菜单进行返回
                }).sorted(Comparator.comparingInt(menu -> (menu.getSort() == null ? 0 : menu.getSort())))
                .collect(Collectors.toList());
    }
}
